/*
 * @(#) SeqServiceImpl.java  1.0  2004-4-12
 *
 * Copyright 2003 by LongTop Corporation.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * LongTop Corporation ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with LongTop.
 */

package com.cnc.bas.seq;

import org.hibernate.LockMode;

import com.cnc.bas.dao.IBasDao;
import com.cnc.bas.util.Constants;
import com.cnc.bas.util.StringUtil;
import com.cnc.ssm.model.PwSqSetting;
import com.cnc.ssm.model.PwSqVal;


/**
 * User: Du bf
 * Date: 2004-4-12
 * Time: 16:38:20
 */
public class SeqServiceImpl implements ISeqService {

    private IBasDao basDao;

    public IBasDao getBasDao() {
        return basDao;
    }

    public void setBasDao(IBasDao basDao) {
        this.basDao = basDao;
    }

    /**
     * IDKey="ID"
     *
     * @param key
     * @return generated id
     * @throws com.cnc.bas.seq.SequenceException
     *
     */
    public Long getID(String key) throws SequenceException {
        PwSqSetting seq = SeqgenSettingManager.getInstance(basDao).getSeqSetting(Constants.IDKey);
        if (seq == null) throw new SequenceException(Constants.IDKey);
        return getNextValue(key, seq);
    }

    public String getSequenceNo(String key, String officeCode) throws SequenceException {
        PwSqSetting seq = SeqgenSettingManager.getInstance(basDao).getSeqSetting(key);
        if (seq == null) throw new SequenceException(key);
        String seqKey = officeCode;

        Long currentValue = this.getNextValue(seqKey, seq);
        String seqNo = seqKey + StringUtil.leftPad(currentValue.toString(), seq.getSqLen().intValue(), "0");
        return seqNo;
    }

    private Long getNextValue(String key, PwSqSetting seq) throws SequenceException {
        int blockSize = seq.getBlockCount().intValue();
        if (blockSize == 0) blockSize = 1;
        Long nextValue = (Long) SeqgenSettingManager.getInstance(basDao).getLastValue().get(key);
        if (nextValue == null) {
            PwSqVal seqValue = (PwSqVal) basDao.load(PwSqVal.class, key);
            if (seqValue == null) {
                seqValue = new PwSqVal();
                seqValue.setCurrVal(new Long(blockSize));
                seqValue.setSqKey(key);
                basDao.add(seqValue);
                SeqgenSettingManager.getInstance(basDao).getLastValue().put(key, new Long(1));
                return new Long(1);
            } else {
                nextValue = new Long(seqValue.getCurrVal().longValue() + 1);
                seqValue.setCurrVal(new Long(blockSize + seqValue.getCurrVal().longValue()));
                basDao.update(seqValue);
                SeqgenSettingManager.getInstance(basDao).getLastValue().put(key, nextValue);
                return nextValue;
            }
        } else if (nextValue.longValue() % blockSize == 0) {
            PwSqVal seqValue = (PwSqVal) basDao.load(PwSqVal.class, key, LockMode.UPGRADE);
            if (seqValue == null) throw new SequenceException(key);
            long currentValue = seqValue.getCurrVal().longValue();
            seqValue.setCurrVal(new Long(blockSize + currentValue));
            basDao.update(seqValue);
            return new Long(currentValue + 1);
        } else {
            nextValue = new Long(nextValue.longValue() + 1);
            SeqgenSettingManager.getInstance(basDao).getLastValue().put(key, nextValue);
            return nextValue;
        }
    }
}

